package com.jfree.netty.server;

import com.jfree.netty.handler.ChildChannelHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.NettyRuntime;
import io.netty.util.internal.SystemPropertyUtil;

/**
 * @author wangjian
 * @date 2019/10/23 16:56
 */
public class Server {

    //编码器
    //https://www.jianshu.com/p/c90ec659397c
    //https://blog.csdn.net/thinking_fioa/article/details/80573483
    //channel pipeline channelcontext xxxstrap等api和源码详解？？？
    public static void main(String[] args) throws Exception {
        System.out.println("HELLO, WORLD".getBytes().length);
        System.out.println(new Integer(12).byteValue());

        new Server().bind(4561);

    }
      //TODO NETTY IO多路复用（设计netty线程模型）？？？
    public void bind(int port) throws Exception {
        EventLoopGroup boss = new NioEventLoopGroup(1); //TODO nioEventLoopGroup要详解，看看他的线程池数组里面每个池子里面有多少线程？？？
        EventLoopGroup work = new NioEventLoopGroup(4);
        //TODO EventLoop是只有一个线程吗？但是测试的时候发现在业务线程中发送信息的线程和在nett线程是不一样的，并且，
        // 同一个channel io操作测试是同一个线程，可以再研究下，这对理解netty线程模型有好处
        //  且同一个线程操作io有可能堵塞其他绑定的channel的io操作的。。。
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(boss, work)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .childHandler(new ChildChannelHandler());
        try {
            ChannelFuture f = serverBootstrap.bind(port).sync();
            //channelFuture  可以回调事件
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }

    public void test1() {
        CompositeByteBuf message = Unpooled.compositeBuffer();
        ByteBuf header = Unpooled.buffer();
        ByteBuf body = Unpooled.directBuffer();

        message.addComponents(header, body);
        for (ByteBuf buf : message) {
            System.out.println(buf.toString());
        }
        int length = message.readableBytes();
        byte[] array = new byte[length];
        //将字节读到array数组中
        message.getBytes(message.readerIndex(), array);
        PooledByteBufAllocator pool = new PooledByteBufAllocator();
        ByteBuf dirctBuf = pool.directBuffer("df".getBytes().length);
        dirctBuf.release();
    }

}
